#ifndef __PULSED_THREAD_H__
#define __PULSED_THREAD_H__

#include "non_copyable.h"
#include "callback.h"
#include "thread.h"
#include "timer.h"
#include "manual_event.h"
#include "shared_ptr.h"
#include "sync_obj.h"
#include "mutex.h"


namespace Boss
{

  class PulsedThread
    : private NonCopyable
  {
  public:
    PulsedThread(ICallbackPtr callback, unsigned period)
      : IsRun(true)
      , Callback(callback)
    {
      Event_.Reset();
      Thread_.Reset(new Thread(CreateMemberCallback(*this, &PulsedThread::Loop)));
      Timer_.Reset(new Timer(CreateMemberCallback(*this, &PulsedThread::Resume), period));
    }
    ~PulsedThread()
    {
      {
        SyncObj<Mutex> Lock(Mutex_);
        IsRun = false;
        Event_.Set();
      }
      Thread_.Release();
    }

  private:
    volatile bool IsRun;
    ICallbackPtr Callback;
    Mutex Mutex_;
    ManualEvent Event_;
    SharedPtr<Thread> Thread_;
    SharedPtr<Timer> Timer_;
    void Resume()
    {
      SyncObj<Mutex> Lock(Mutex_);
      Event_.Set();
    }
    void Loop()
    {
      for ( ; ; )
      {
        try
        {
          if (IsRun)
            Event_.Wait();
          else
            break;
          if (IsRun)
            Callback->Do();
          else
            break;
          {
            SyncObj<Mutex> Lock(Mutex_);
            if (IsRun)
              Event_.Reset();
            else
              break;
          }
        }
        catch (std::exception &)
        {
        }
      }
    }
  };

}

#endif  // !__PULSED_THREAD_H__
